﻿
using CStoreBulk.Content;
using CStoreBulk.Entities;
using CStoreBulk.Utilities;
using Dicom;
using Dicom.Imaging;
using Dicom.Network;
using Dicom.Network.Client;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CStoreBulk
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window,INotifyPropertyChanged
    {
        private string sysMessage;
        //消息
        public string SysMessage
        {
            get { return sysMessage; }
            set { sysMessage = value; RaisePropertyChanged(nameof(SysMessage)); }
        }

        private ObservableCollection<String> queueItem;

        public ObservableCollection<String> QueueItem
        {
            get { return queueItem; }
            set { queueItem = value; }
        }

        private ObservableCollection<String> messages;
        public ObservableCollection<String> Messages
        {
            get { return messages; }
            set { messages = value; }
        }

        private int missionCount;

        public event PropertyChangedEventHandler PropertyChanged;

        public int MissionCount
        {
            get { return QueueItem.Count; }
            private set 
            { 
                missionCount = value; 
                RaisePropertyChanged(nameof(MissionCount)); 
            }
        }

        private int finishedMissionCount;

        public int FinishedMissionCount
        {
            get { return finishedMissionCount; }
            set { finishedMissionCount = value; RaisePropertyChanged(nameof(FinishedMissionCount)); }
        }

        private int storeProgress;

        public int StoreProgress
        {
            get { return storeProgress; }
            set { storeProgress = value; RaisePropertyChanged(nameof(StoreProgress)); }
        }

        private int failedCount;

        public int FailedCount
        {
            get { return failedCount; }
            set { failedCount = value; RaisePropertyChanged(nameof(FailedCount)); }
        }



        private static string StoreServerHost = string.Empty;
        private static int StoreServerPort = 0;
        private static  string StoreServerAET = string.Empty;
        private static  string LocalAET = string.Empty;
        private string workDirectory = string.Empty;
        private StoreSetting _serverSetting;


        public MainWindow()
        {
            InitializeComponent();
            QueueItem = new ObservableCollection<string>();
            Messages = new ObservableCollection<string>();
            this.DataContext = this;
            this.Loaded += MainWindow_Loaded;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            if (File.Exists("StoreSetting.json"))
            {
                _serverSetting = JsonConvert.DeserializeObject<StoreSetting>(File.ReadAllText("StoreSetting.json"));
                //this.ServerIP.Text = serverSetting.ServerIP;
                //this.ServerPort.Text = serverSetting.ServerPort.ToString();
                //this.ServerAE.Text = serverSetting.ServerAET;
                //this.LocalAE.Text = serverSetting.LocalAET;
            }
        }

        //打开一个dicom文件
        private void Open_File_Click(object sender, RoutedEventArgs e)
        {
            string targetFile = string.Empty;
            Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog
            {
                DefaultExt = ".dcm",
                Filter = "dicom file|*.dcm"
            };
            if (ofd.ShowDialog() == true)
            {
                targetFile = ofd.FileName;
                SysMessage = "已新增一个文件";
                Messages.Add(SysMessage);
            }
            QueueItem.Add(targetFile);
            RaisePropertyChanged(nameof(MissionCount));
        }

        /// <summary>
        /// 同步执行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Go_Click(object sender, RoutedEventArgs e)
        {

            if(QueueItem.Count <= 0)
            {
                SysMessage = "未添加任何Dicom文件,无法执行存储";
                return;
            }
            if(string.IsNullOrEmpty(_serverSetting.ServerIP) ||
                _serverSetting.ServerPort == 0 ||
                string.IsNullOrEmpty(_serverSetting.ServerAET) ||
                string.IsNullOrEmpty(_serverSetting.LocalAET)
                )
            {
                MessageBox.Show("服务端设置缺失");
                return;
            }
            var client = new Dicom.Network.Client.DicomClient(_serverSetting.ServerIP, _serverSetting.ServerPort, false, _serverSetting.LocalAET, _serverSetting.ServerAET);
            client.NegotiateAsyncOps();

            foreach (var item in QueueItem)
            {
                try
                {
                    var request = new DicomCStoreRequest(item);
                    request.OnResponseReceived += (req, response) =>
                    {
                        int index = item.LastIndexOf("\\");
                        string fileName = item.Substring(index + 1);
                        //Messages.Add("C-Store Response Received, Status: " + response.Status);
                        if (((DicomCStoreResponse)response).Status.Code == 0)
                        {
                            FinishedMissionCount++;
                            StoreProgress = (int)((float)FinishedMissionCount / (float)MissionCount) * 100;
                            
                            ThreadPool.QueueUserWorkItem(delegate
                            {
                                System.Threading.SynchronizationContext.SetSynchronizationContext(new
                                    System.Windows.Threading.DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
                                System.Threading.SynchronizationContext.Current.Post(pl =>
                                {
                                    //里面写真正的业务内容
                                    Messages.Add($"文件{fileName}已成功存储!");
                                }, null);
                            });
                           
                        }
                        else
                        {
                            ThreadPool.QueueUserWorkItem(delegate
                            {
                                System.Threading.SynchronizationContext.SetSynchronizationContext(new
                                    System.Windows.Threading.DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
                                System.Threading.SynchronizationContext.Current.Post(pl =>
                                {
                                    //里面写真正的业务内容
                                    Messages.Add($"文件{fileName}存储失败！{((DicomCStoreResponse)response).Status.Description}");
                                    FailedCount++;
                                }, null);
                            });
                        }
                    };
                    await client.AddRequestAsync(request);
                    Messages.Add($"准备存储...");
                    await client.SendAsync();
                }
                catch (Exception ex)
                {
                    Messages.Add($"存储发生异常:{ex.Message}");
                }
            }
        }

        ////异步执行
        //private void Go_Async_Click(object sender, RoutedEventArgs e)
        //{

        //}

        /// <summary>
        /// 清空所有文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void File_CleanAll_Click(object sender, RoutedEventArgs e)
        {
            QueueItem.Clear();
            MissionCount = 0;
        }

        public  void RaisePropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// 打开文件夹
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void File_Open_Folder_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog();
            dialog.Description = "请选择DICOM文件所在文件夹";
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                if (string.IsNullOrEmpty(dialog.SelectedPath))
                {
                    System.Windows.MessageBox.Show(this, "文件夹路径不能为空", "提示");
                    return;
                }
                else
                {
                    workDirectory = dialog.SelectedPath;
                }
                //create a new thread to find dicom files recursively;
                Task.Run(()=>
                {
                    var results = Searchable.FindFileRecursively(workDirectory);
                    results.ForEach(item =>
                    {
                        QueueItem.Add(item);
                    });
                })
                .ContinueWith(task =>
                {
                    SysMessage = "已全部加载";
                    RaisePropertyChanged(nameof(SysMessage));
                    RaisePropertyChanged(nameof(MissionCount));
                });
            }
        }

        private void Settings_General_Click(object sender, RoutedEventArgs e)
        {
            SettingWindow settingw = new SettingWindow();
            settingw.ShowDialog();
        }

        /// <summary>
        /// 导出日志
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Settings_DumpLog_Click(object sender, RoutedEventArgs e)
        {
            StringBuilder sbuilder = new StringBuilder();
            foreach(var item in messages)
            {
                sbuilder.Append(item + Environment.NewLine);
            }
            File.WriteAllText($"{DateTime.Now.ToString("yyyy-MM-dd")}.log", sbuilder.ToString());
            return;
        }

        private async void Run_Print_Click(object sender, RoutedEventArgs e)
        {
            if(QueueItem.Count < 0)
            {
                Messages.Add("当前队列中没有任何文件，请先添加文件！");
            }
            if(QueueItem.Count > 1)
            {
                var result = MessageBox.Show("当前队列存在多个文件，是否全部打印？","提示",MessageBoxButton.YesNo,MessageBoxImage.Warning);
                if(result == MessageBoxResult.No)
                {
                    return;
                }
            }

            var stopwatch = new System.Diagnostics.Stopwatch();
            stopwatch.Start();
            var serverSetting = ConfigBus.LoadStoreSetting();
            var printerSetting = ConfigBus.LoadPrintSetting();
            var printJob = new PrintJob("DICOM_PRINT_JOB")
            {
                RemoteAddress = serverSetting.ServerIP,
                RemotePort = serverSetting.ServerPort,
                CallingAE = serverSetting.LocalAET,
                CalledAE = serverSetting.ServerAET,
            };

            foreach(var dcm in QueueItem)
            {
                var greyscaleImg = new DicomImage(dcm);
                using (var bitmap = greyscaleImg.RenderImage().As<Bitmap>())
                {
                    printJob.StartFilmBox("STANDARD\\1,1", printerSetting.FilmDirection, printerSetting.FilmSize);
                    printJob.FilmSession.IsColor = false; //set to true to print in color
                    printJob.AddImage(bitmap, 0);
                    printJob.EndFilmBox();
                }
                await printJob.Print();

                stopwatch.Stop();
                var costTime = stopwatch.Elapsed.TotalSeconds;
                Messages.Add($"{dcm}打印完成，耗时:{costTime}s");
            }
        }

        /// <summary>
        /// 执行CMOVE
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Run_CMove_Click(object sender, RoutedEventArgs e)
        {

        }

        /// <summary>
        /// 查询worklist服务中所有病人登记信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Run_QueryWorkList_Click(object sender, RoutedEventArgs e)
        {
            var worklistSetting = ConfigBus.LoadWorkListSetting();
            QueryFilter qf = new QueryFilter();
            qf.OnExecuteQuery += async (name, id, dateRange) =>
            { 
                List<DicomDataset> workListItems = await GetAllItemsFromWorklistAsync(worklistSetting.ServerIP, worklistSetting.ServerPort, worklistSetting.ServerAET, worklistSetting.LocalAET, name, id, dateRange);
                if(workListItems.Any())
                {
                    Messages.Add($"发现记录{workListItems.Count}条");
                    foreach(var worklist in workListItems)
                    {
                        string patintName = worklist.GetString(DicomTag.PatientName);
                        string studyUID = worklist.GetString(DicomTag.StudyInstanceUID);
                        string createTime = worklist.GetString(DicomTag.AccessionNumber);
                        Messages.Add($"病人:{patintName},StudyUID:{studyUID},AccessionNumber：{createTime}");
                    }
                }
                else
                {
                    Messages.Add("未查询到任何记录。");
                }
            };
            qf.ShowDialog();

        }

        /// <summary>
        /// 执行C-GET
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Run_CGet_Click(object sender, RoutedEventArgs e)
        {
            C_Find_Get_Win findGet = new C_Find_Get_Win();
            findGet.ShowDialog();
        }


        private static async Task<List<DicomDataset>> GetAllItemsFromWorklistAsync(string serverIP, int serverPort, string serverAET, string clientAET,string patientName = "",string patientID = "",int dateRange = 0)
        {
            var worklistItems = new List<DicomDataset>();
            var cfind = DicomCFindRequest.CreateWorklistQuery(patientID,patientName,"","","",new DicomDateRange(DateTime.Now,DateTime.Now.AddDays(-dateRange))); // no filter, so query all awailable entries
            cfind.OnResponseReceived = (DicomCFindRequest rq, DicomCFindResponse rp) =>
            {
                if (rp.HasDataset)
                {
                    Console.WriteLine("Study UID: {0}", rp.Dataset.GetSingleValue<string>(DicomTag.StudyInstanceUID));
                    worklistItems.Add(rp.Dataset);
                }
                else
                {
                    Console.WriteLine(rp.Status.ToString());
                }
            };

            var client = new Dicom.Network.Client.DicomClient(serverIP, serverPort, false, clientAET, serverAET);
            await client.AddRequestAsync(cfind);
            await client.SendAsync();

            return worklistItems;
        }
    }
}
